﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace JT808Protocol.Models.Enums
{
    /// <summary>
    /// 终端参数设置各参数项定义
    /// </summary>
    public enum EnumDeviceParamType
    {
        //未定义默认为保留
        保留 = 0x0000,

        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        终端心跳发送间隔 = 0x0001,

        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        TCP消息应答超时时间 = 0x0002,

        [DeviceParamTypeDescription("DWORD")]
        TCP消息重传次数 = 0x0003,

        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        UDP消息应答超时时间 = 0x0004,

        [DeviceParamTypeDescription("DWORD")]
        UDP消息重传次数 = 0x0005,

        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        SMS消息应答超时时间 = 0x0006,

        [DeviceParamTypeDescription("DWORD")]
        SMS消息重传次数 = 0x0007,

        [DeviceParamTypeDescription("STRING")]
        主服务器APN = 0x0010,

        [DeviceParamTypeDescription("STRING")]
        主服务器无线通信拨号用户名 = 0x0011,

        [DeviceParamTypeDescription("STRING")]
        主服务器无线通信拨号密码 = 0x0012,

        [DeviceParamTypeDescription("STRING")]
        主服务器地址_IP_或域名 = 0x0013,

        [DeviceParamTypeDescription("STRING")]
        备份服务器APN = 0x0014,

        [DeviceParamTypeDescription("STRING")]
        备份服务器无线通信拨号用户名 = 0x0015,

        [DeviceParamTypeDescription("STRING")]
        备份服务器无线通信拨号密码 = 0x0016,

        [DeviceParamTypeDescription("STRING")]
        备份服务器地址_IP_或域名 = 0x0017,

        [DeviceParamTypeDescription("DWORD")]
        服务器TCP端口 = 0x0018,

        [DeviceParamTypeDescription("DWORD")]
        服务器UDP端口 = 0x0019,

        [DeviceParamTypeDescription("STRING")]
        道路运输证IC卡认证主服务器IP地址或域名 = 0x001A,

        [DeviceParamTypeDescription("DWORD")]
        道路运输证IC卡认证主服务器TCP端口 = 0x001B,

        [DeviceParamTypeDescription("DWORD")]
        道路运输证IC卡认证主服务器UDP端口 = 0x001C,

        [DeviceParamTypeDescription("STRING")]
        道路运输证IC卡认证备份服务器IP地址或域名 = 0x001D,

        /// <summary>
        /// 位置汇报策略
        /// 0：定时汇报；1：定距汇报；2：定时和定距汇报
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        位置汇报策略 = 0x0020,

        /// <summary>
        /// 位置汇报方案
        /// 0：根据 ACC 状态； 1：根据登录状态和 ACC 状态,先判断登录状态,若登录再根据 ACC 状态
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        位置汇报方案 = 0x0021,

        /// <summary>
        /// 驾驶员未登录汇报时间间隔,单位为秒(s),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        驾驶员未登录汇报时间间隔 = 0x0022,

        /// <summary>
        /// 休眠时汇报时间间隔,单位为秒(s),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        休眠时汇报时间间隔 = 0x0027,

        /// <summary>
        /// 紧急报警时汇报时间间隔,单位为秒(s),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        紧急报警时汇报时间间隔 = 0x0028,

        /// <summary>
        /// 缺省时间汇报间隔,单位为秒(s),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        缺省时间汇报间隔 = 0x0029,

        /// <summary>
        /// 缺省距离汇报间隔,单位为米(m),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为米(m)")]
        缺省距离汇报间隔 = 0x002C,

        /// <summary>
        /// 驾驶员未登录汇报距离间隔,单位为米(m),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为米(m)")]
        驾驶员未登录汇报距离间隔 = 0x002D,

        /// <summary>
        /// 休眠时汇报距离间隔,单位为米(m),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为米(m)")]
        休眠时汇报距离间隔 = 0x002E,

        /// <summary>
        /// 紧急报警时汇报距离间隔,单位为米(m),>0
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为米(m)")]
        紧急报警时汇报距离间隔 = 0x002F,

        /// <summary>
        /// 拐点补传角度,<180
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        拐点补传角度 = 0x0030,

        /// <summary>
        /// 电子围栏半径(非法位移阈值)
        /// 单位为米
        /// </summary>
        [DeviceParamTypeDescription("WORD", "单位为米(m)")]
        电子围栏半径 = 0x0031,

        [DeviceParamTypeDescription("STRING")]
        监控平台电话号码 = 0x0040,

        /// <summary>
        /// 复位电话号码,可采用此电话号码拨打终端电话让终端复位
        /// </summary>
        [DeviceParamTypeDescription("STRING")]
        复位电话号码 = 0x0041,

        /// <summary>
        /// 恢复出厂设置电话号码,可采用此电话号码拨打终端电话让终端恢复出厂设置
        /// </summary>
        [DeviceParamTypeDescription("STRING")]
        恢复出厂设置电话号码 = 0x0042,

        [DeviceParamTypeDescription("STRING")]
        监控平台SMS电话号码 = 0x0043,

        [DeviceParamTypeDescription("STRING")]
        接收终端SMS文本报警号码 = 0x0044,

        /// <summary>
        /// 终端电话接听策略
        /// 0：自动接听；1：ACC ON 时自动接听,OFF 时手动接听
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        终端电话接听策略 = 0x0045,

        /// <summary>
        /// 每次最长通话时间,单位为秒(s),0 为不允许通话,0xFFFFFFFF 为不限制
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        每次最长通话时间 = 0x0046,

        /// <summary>
        /// 当月最长通话时间,单位为秒(s),0 为不允许通话,0xFFFFFFFF 为不限制
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        当月最长通话时间 = 0x0047,

        [DeviceParamTypeDescription("STRING")]
        监听电话号码 = 0x0048,

        [DeviceParamTypeDescription("STRING")]
        监管平台特权短信号码 = 0x0049,

        /// <summary>
        /// 报警屏蔽字,与位置信息汇报消息中的报警标志相对应,相应位为 1则相应报警被屏蔽
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        报警屏蔽字 = 0x0050,

        /// <summary>
        /// 报警发送文本 SMS 开关,与位置信息汇报消息中的报警标志相对应,相应位为 1 则相应报警时发送文本 SMS
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        报警发送文本SMS开关 = 0x0051,

        /// <summary>
        /// 报警拍摄开关,与位置信息汇报消息中的报警标志相对应,相应位为1 则相应报警时摄像头拍摄
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        报警拍摄开关 = 0x0052,

        /// <summary>
        /// 报警拍摄存储标志,与位置信息汇报消息中的报警标志相对应,相应位为 1 则对相应报警时拍的照片进行存储,否则实时上传
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        报警拍摄存储标志 = 0x0053,

        /// <summary>
        /// 关键标志,与位置信息汇报消息中的报警标志相对应,相应位为 1 则对相应报警为关键报警
        /// </summary>
        关键标志 = 0x0054,

        /// <summary>
        /// 最高速度,单位为公里每小时(km/h)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为公里每小时(km/h)")]
        最高速度 = 0x0055,

        /// <summary>
        /// 超速持续时间,单位为秒(s)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        超速持续时间 = 0x0056,

        /// <summary>
        /// 连续驾驶时间门限,单位为秒(s)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        连续驾驶时间门限 = 0x0057,

        /// <summary>
        /// 当天累计驾驶时间门限,单位为秒(s)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        当天累计驾驶时间门限 = 0x0058,

        /// <summary>
        /// 最小休息时间,单位为秒(s)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        最小休息时间 = 0x0059,

        /// <summary>
        /// 最长停车时间,单位为秒(s)
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为秒(s)")]
        最长停车时间 = 0x005A,

        /// <summary>
        /// 超速报警预警差值,单位为 1/10Km/h
        /// </summary>
        [DeviceParamTypeDescription("WORD", "单位为1/10Km/h")]
        超速报警预警差值 = 0x005B,

        /// <summary>
        /// 疲劳驾驶预警差值,单位为秒(s),>0
        /// </summary>
        [DeviceParamTypeDescription("WORD", "单位为秒(s)")]
        疲劳驾驶预警差值 = 0x005C,

        /// <summary>
        /// 碰撞报警参数设置
        /// b7 - b0： 碰撞时间,单位 4ms
        /// b15 - b8：碰撞加速度,单位 0.1g,设置范围在：0 - 79 之间,默认为10
        /// </summary>
        [DeviceParamTypeDescription("WORD")]
        碰撞报警参数设置 = 0x005D,

        /// <summary>
        /// 侧翻报警参数设置
        /// 侧翻角度,单位 1 度,默认为 30 度
        /// </summary>
        [DeviceParamTypeDescription("WORD")]
        侧翻报警参数设置 = 0x005E,

        [DeviceParamTypeDescription("DWORD")]
        定时拍照控制 = 0x0064,

        [DeviceParamTypeDescription("DWORD")]
        定距拍照控制 = 0x0065,

        [DeviceParamTypeDescription("DWORD")]
        图像视频质量 = 0x0070,

        [DeviceParamTypeDescription("DWORD")]
        亮度 = 0x0071,

        [DeviceParamTypeDescription("DWORD")]
        对比度 = 0x0072,

        [DeviceParamTypeDescription("DWORD")]
        饱和度 = 0x0073,

        [DeviceParamTypeDescription("DWORD")]
        色度 = 0x0074,

        [DeviceParamTypeDescription("DWORD", "单位为 1/10km")]
        车辆里程表读数 = 0x0080,

        [DeviceParamTypeDescription("WORD")]
        车辆所在的省域ID = 0x0081,

        [DeviceParamTypeDescription("WORD")]
        车辆所在的市域ID = 0x0082,

        [DeviceParamTypeDescription("STRING")]
        公安交通管理部门颁发的机动车号牌 = 0x0083,

        [DeviceParamTypeDescription("BYTE")]
        车牌颜色 = 0x0084,

        /// <summary>
        /// GNSS定位模式
        ///  bit0,0：禁用 GPS 定位, 1：启用 GPS 定位
        ///  bit1,0：禁用北斗定位, 1：启用北斗定位
        ///  bit2,0：禁用 GLONASS 定位, 1：启用 GLONASS 定位
        ///  bit3,0：禁用 Galileo 定位, 1：启用 Galileo 定位
        /// </summary>
        [DeviceParamTypeDescription("BYTE")]
        GNSS定位模式 = 0x0090,

        /// <summary>
        /// GNSS 波特率
        /// 0x00：4800
        /// 0x01：9600
        /// 0x02：19200
        /// 0x03：38400
        /// 0x04：57600
        /// 0x05：115200
        /// </summary>
        [DeviceParamTypeDescription("BYTE")]
        GNSS波特率 = 0x0091,

        /// <summary>
        /// GNSS 模块详细定位数据输出频率
        /// 0x00：500ms
        /// 0x01：1000ms(默认值)
        /// 0x02：2000ms
        /// 0x03：3000ms
        /// 0x04：4000ms
        /// </summary>
        [DeviceParamTypeDescription("BYTE")]
        GNSS模块详细定位数据输出频率 = 0x0092,

        /// <summary>
        /// GNSS 模块详细定位数据采集频率,单位为秒,默认为 1。
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        GNSS模块详细定位数据采集频率 = 0x0093,

        /// <summary>
        /// GNSS 模块详细定位数据上传方式
        /// 0x00,本地存储,不上传(默认值)
        /// 0x01,按时间间隔上传
        /// 0x02,按距离间隔上传
        /// 0x0B,按累计时间上传,达到传输时间后自动停止上传
        /// 0x0C,按累计距离上传,达到距离后自动停止上传
        /// 0x0D,按累计条数上传,达到上传条数后自动停止上传
        /// </summary>
        [DeviceParamTypeDescription("BYTE")]
        GNSS模块详细定位数据上传方式 = 0x0094,

        /// <summary>
        /// GNSS 模块详细定位数据上传设置
        /// 上传方式为 0x01 时,单位为秒
        /// 上传方式为 0x02 时,单位为米
        /// 上传方式为 0x0B 时,单位为秒
        /// 上传方式为 0x0C 时,单位为米
        /// 上传方式为 0x0D 时,单位为条
        /// </summary>
        [DeviceParamTypeDescription("DWORD")]
        GNSS模块详细定位数据上传设置 = 0x0095,

        /// <summary>
        /// CAN 总线通道 1 采集时间间隔(ms),0 表示不采集
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为毫秒(ms),0 表示不采集")]
        CAN总线通道1采集时间间隔 = 0x0100,

        /// <summary>
        /// CAN 总线通道 1 上传时间间隔(s),0 表示不上传
        /// </summary>
        [DeviceParamTypeDescription("WORD", "单位为秒(s),0 表示不上传")]
        CAN总线通道1上传时间间隔 = 0x0101,

        /// <summary>
        /// CAN 总线通道 2 采集时间间隔(ms),0 表示不采集
        /// </summary>
        [DeviceParamTypeDescription("DWORD", "单位为毫秒(ms),0 表示不采集")]
        CAN总线通道2采集时间间隔 = 0x0102,

        /// <summary>
        /// CAN 总线通道 2 上传时间间隔(s),0 表示不上传
        /// </summary>
        [DeviceParamTypeDescription("WORD", "单位为毫秒(ms),0 表示不上传")]
        CAN总线通道2上传时间间隔 = 0x0103,

        /// <summary>
        /// CAN 总线 ID 单独采集设置
        /// bit63-bit32 表示此 ID 采集时间间隔(ms),0 表示不采集
        /// bit31 表示 CAN 通道号,0：CAN1,1：CAN2
        /// bit30 表示帧类型,0：标准帧,1：扩展帧
        /// bit29 表示数据采集方式,0：原始数据,1：采集区间的计算值
        /// bit28-bit0 表示 CAN 总线 ID
        /// </summary>
        CAN总线ID单独采集设置 = 0x0110,
    }

    /// <summary>
    /// 终端参数类型描述
    /// </summary>
    public class DeviceParamTypeDescription : Attribute
    {
        public string UnitDesc { get; set; }
        public string DataType { get; set; }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="UnitDesc">单位秒数</param>
        /// <param name="DataType">数据类型</param>
        public DeviceParamTypeDescription(string DataType, string UnitDesc = "")
        {
            this.UnitDesc = UnitDesc;
            this.DataType = DataType;
        }
    }

    public static class EnumDeviceParamTypeHelper
    {
        public static IEnumerable<(string key, int value)> GetEnum()
        {
            return Enum.GetValues(typeof(EnumDeviceParamType))
              .Cast<int>()
              .Select(e =>
              {
                  //跳过第一个保留项和最后几个byte[]的
                  if (e == 0x0000 || e >= 0x0110) return ("", 0);

                  return (Enum.GetName(typeof(EnumDeviceParamType), e), e);
              }).Where((key, e) => !string.IsNullOrEmpty(key.Item1));
        }

        public static DeviceParamTypeDescription GetDescription(this Enum value)
        {
            Type type = value.GetType();

            FieldInfo fieldInfo = type.GetField(value.ToString());

            DeviceParamTypeDescription[] attribs = fieldInfo.GetCustomAttributes(
                typeof(DeviceParamTypeDescription), false) as DeviceParamTypeDescription[];

            return attribs.Length > 0 ? attribs[0] : null;
        }
    }
}